/*
 * FileReader.c
 *
 *  Created on: Jan 24, 2012
 *      Author: Ivan
 */
#include "FileReader.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <assert.h>

/*
 * fseek(f, 0, SEEK_END); // seek to end of file
	size = ftell(f);
 */
int amount;
int zeropoints[50];

int main()
{
	/*hexdump to read*/

	/*
	system("objcopy -I ihex Hex.hex  -O binary Hex.bin");
	*/
		ILIST *list;
		char *s;
		s=malloc(3000*sizeof(char));
	    int length;
	    printf("Input File Name:");
	    scanf("%s", s);
	    char *extension=malloc(100*sizeof(char));
	    length = strlen(s);
	    strcat(extension,&s[length-3]);
	    char*output=malloc(100*sizeof(char));
	   strncpy( output, s, length-4 );


	    if(strncmp(extension,"hex",3)==0)
	       {

	    	convertHex(output);
			list= ReadBinFileIvanStyleInt(strcat(output,".bin"));
	        }
	       else if(strncmp(extension,"elf",3)==0)
	       {
	    	   convertelf(output);
		       list= ReadBinFileIvanStyleInt(strcat(output,".bin"));

	       }
	       else if(strncmp(extension,"bin",3)==0)
	       {
	    	  list= ReadBinFileIvanStyleInt(s);
	       }
	       else
	       {
	    	   perror("Invalid input");
	       }




	return 0;
}


ILIST * NewInstructionList()
    {
       ILIST *l;
       l = malloc(sizeof(ILIST));
       if (! l)
       { perror("Out of memory! Aborting...");
           exit(10);
       } /* fi */
       l->Length = 0;
       l->First = NULL;
       l->Last = NULL;
       return l;
       /* end of NewInstructionList */
    }

/* delete a instruction list (and all entries) */
void DeleteInstructionList(ILIST *l)
{
   IENTRY *e, *n;
   assert(l);
   e = l->First;
   while(e)
   { n = e->Next;
       free(e);
       e = n;
   }
   free(l);
   /* end of DeleteImageList */
}


/* insert an instruction into a list */
void AppendInstruction(ILIST *l, int y)
{
   IENTRY *e = NULL;
   assert(l);
   e = malloc(sizeof(IENTRY));
   if (! e)
   { perror("Out of memory! Aborting...");
       exit(10);
   } /* fi */;

    e->instruction =y;
   if (l->Last)
   { e->List = l;
       e->Next = NULL;
       e->Prev = l->Last;
       l->Last->Next = e;
       l->Last = e;
   }
   else
   { e->List = l;
       e->Next = NULL;
       e->Prev = NULL;
       l->First = e;
       l->Last = e;
   }
   l->Length++;
}



ILIST * ReadBinFile (char * fname)
{

    /*test file*/
    /*
    char fname[8] = "bin.bin";
    */

    /* size_t result; */

    FILE *fp;

    fp=fopen(fname, "rb");

    fseek(fp, 0, SEEK_END); /* seek to end of file*/
    int size = ftell(fp); /*get current file pointer*/
    fseek(fp, 0, SEEK_SET);

     int *x;
    x=malloc(size*100*sizeof( int));

    ILIST * Instruction_List = NewInstructionList();

    /*read file*/
    if (fp)
    {
    	fread(x,4,(size/4),fp);

    }
    else
    {
    	perror("error. could not open file");
    	exit(10);
   }
    int i=0;
    	while(i<(size/4))
    		{
    			int j=x[1];
    			AppendInstruction(Instruction_List,j);
    			i++;

    		}






   fclose(fp);


   Test_Instruction(Instruction_List);
   return Instruction_List;

}



void convertelf(char *x)  /*this function takes the user inputted .elf file, then converts it to a binary file*/
{
	/*stores the filename*/
		char *filename=malloc(3000*sizeof(char));
		strcpy(filename,x);
		/*filename Hex*/

		/*takes first string argument*/
		char *firstl;
		char *first=malloc(3000*sizeof(char));;
		firstl="objcopy  -I  ";
		strcpy(first,firstl);
		/*first objcopy -I ihex*/


		/*last part */
		char *last=malloc(3000*sizeof(char));
		char*lastl;
		lastl=" -j .data -O binary ";
		strcpy(last,lastl);
		/*last -0 binary*/


		char *outputname=malloc(2000*sizeof(char));
		strcpy(outputname,filename);
		strcat(outputname,".bin");

		/*output name .bin*/

		char *inputname=malloc(2000*sizeof(char));
			strcpy(inputname,filename);
			strcat(inputname,".elf");
			/*input name */

		/*inputname hex.hex last -o binary first objcopy output name hex.bin*/

		strcat(first,inputname);
		strcat(first,last);
		strcat(first,outputname);


		system(first); /*calls the function on the command prompt, using the objcopy utility on the ladera server*/


	/*freeing allocated memory for the string*/ /* always returns this converted file name for the binary handling portion of the API*/
}
void convertHex(char *x)  /*this function takes the user inputted .elf file, then converts it to a binary file*/
{
	/*stores the filename*/
	char *filename=malloc(3000*sizeof(char));
	strcpy(filename,x);
	/*filename Hex*/

	/*takes first string argument*/
	char *firstl;
	char *first=malloc(3000*sizeof(char));;
	firstl="objcopy -I ihex ";
	strcpy(first,firstl);
	/*first objcopy -I ihex*/


	/*last part */
	char *last=malloc(3000*sizeof(char));
	char*lastl;
	lastl=" -O binary ";
	strcpy(last,lastl);
	/*last -0 binary*/


	char *outputname=malloc(2000*sizeof(char));
	strcpy(outputname,filename);
	strcat(outputname,".bin");

	/*output name .bin*/

	char *inputname=malloc(2000*sizeof(char));
		strcpy(inputname,filename);
		strcat(inputname,".hex");
		/*input name */

	/*inputname hex.hex last -o binary first objcopy output name hex.bin*/

	strcat(first,inputname);
	strcat(first,last);
	strcat(first,outputname);


	system(first); /*calls the function on the command prompt, using the objcopy utility on the ladera server*/


	/*freeing allocated memory for the string*/ /* always returns this converted file name for the binary handling portion of the API*/
}
void Test_Instruction(ILIST *h)
{	int x;
	/*loop to show ints*/
	IENTRY *g=h->First;
	/*not last value*/
	while(g->Next !=NULL)
	{
		x=g->instruction;
		printf("%d\n",x);
		g=g->Next;
	}
	/*last value*/
	printf("%d\n",h->Last->instruction);

}


ILIST * ReadBinFileIvanStyle (char * fname)
{


    /*test file*/
    /*
    char fname[8] = "bin.bin";
    */

    /* size_t result; */
 /*flips to little indie 46000136*/
    FILE *fp;

    fp=fopen(fname, "rb");

    fseek(fp, 0, SEEK_END); /* seek to end of file*/
    int size = ftell(fp); /*get current file pointer*/
    fseek(fp, 0, SEEK_SET);
    fclose(fp);
    fp=fopen(fname, "rb");

    int i=0;


    ILIST * Instruction_List = NewInstructionList();

    /*read file*/
    if (fp)
    {
    	while(i<(size)/4)

   		{			unsigned int addition=0;
    				int j=0;
    				while (j<4)
    				{
    					/*char is 1 byte or 8 bits*/
    					/*inti s 4 bytes or 32 bits*/
    					 char onechar;
    					fread(&onechar, sizeof(char), 1, fp);
    					if(j==0)
    					{
    						addition=addition|onechar;
    						addition=addition<<24;
    						j++;
    					}
    					else if(j==1)
    					{
    						addition=addition|onechar;
    						addition=addition<<16;
    						j++;

    					}
    					else if(j==2)
    					{
    						addition=addition|onechar;
    						 addition=addition<<8;
    						 j++;
    					}
    					else
    					{
    						addition=addition|onechar;
    						j++;
    					}

    				}

        			AppendInstruction(Instruction_List,addition);

    				printf("%d\n",addition);
    				i++;
   		}

    }

    else
    {
    	perror("error. could not open file");
    	exit(10);
   }

	printf("%d\n",0);
    /*
    int k=0;
    	while(k<(size/4))
    		{
    			int j=x[1];
    			AppendInstruction(Instruction_List,j);
    			k++;

    		}
    		*/


   fclose(fp);


   Test_Instruction(Instruction_List);
   return Instruction_List;


}

ILIST * ReadBinFileIvanStyleInt (char * fname)
{

	/*flips the numbers 36014621 when it should be 4621 3601*/

    /*test file*/
    /*
    char fname[8] = "bin.bin";
    */

    /* size_t result; */

    FILE *fp;

    fp=fopen(fname, "rb");

    fseek(fp, 0, SEEK_END); /* seek to end of file*/
    int size = ftell(fp); /*get current file pointer*/
    fseek(fp, 0, SEEK_SET);

    fclose(fp);
    fp=fopen(fname, "rb+");

    int i=0;


    ILIST * Instruction_List = NewInstructionList();

    /*read file*/
    if (fp)
    {
    	while(i<(size)/4)

   		{		unsigned int addition;


   				fread(&addition, sizeof(int), 1, fp);

   			addition=	switchorder(addition);


    			AppendInstruction(Instruction_List,addition);

    			i++;
   		}

    }

    else
    {
    	perror("error. could not open file");
    	exit(10);
   }

/*
    int k=0;
    	while(k<(size/4))
    		{
    			int j=x[1];

    			AppendInstruction(Instruction_List,j);

    			k++;

    		}
*/

   fclose(fp);


   Test_Instruction(Instruction_List);
   return Instruction_List;


}
int switchorder(int x)
{
	unsigned int a,b,c,d,e,f,g,h,returnvalue;
	a=0;
	b=0;
	c=0;
	d=0;
	e=0;
	f=0;
	g=0;
	h=0;
	a=x&0xF0000000;
	b=x&0x0F000000;
	c=x&0x00F00000;
	d=x&0x000F0000;
	e=x&0x0000F000;
	f=x&0x00000F00;
	g=x&0x000000F0;
	h=x&0x0000000F;
	a=a>>24;
	b=b>>24;
	c=c>>8;
	d=d>>8;
	e=e<<8;
	f=f<<8;
	g=g<<24;
	h=h<<24;
	returnvalue=a|b|c|d|e|f|g|h;





	return returnvalue;
}
